﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Shapes.Misc.Serialization
{
    /// <summary>
    /// Delegate for a common TryParse method
    /// </summary>
    /// <typeparam name="T">the type to parse</typeparam>
    /// <param name="input">the string to parse</param>
    /// <param name="result">the value which the input-string contained</param>
    /// <returns>true, if the parsing process was successful, otherwise false</returns>
    public delegate bool TryParseDelegate<T>(string input, out T result);

    /// <summary>
    /// A helper class with some custom parse methods
    /// </summary>
    public static class ParseHelper
    {
        #region Vector3
        /// <summary>
        /// Tries to parse a Vector3
        /// </summary>
        /// <param name="input">the string to parse</param>
        /// <param name="result">the value which the input-string contained</param>
        /// <returns>true, if the parsing process was successful, otherwise false</returns>
        public static bool TryParse(string input, out Vector3 result)
        {
            string[] parts = input.Split(new char[] { '|', '/', ',', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);

            result = new Vector3();
            float x, y, z;
            if (   parts.Length == 3 
                && float.TryParse(parts[0], out x) 
                && float.TryParse(parts[1], out y) 
                && float.TryParse(parts[2], out z))
            {
                result.X = x;
                result.Y = y;
                result.Z = z;
                return true;
            }
            return false;
        }
        /// <summary>
        /// writes all relevant values to a string which can be parsed by ParseHelper.TryParse()
        /// </summary>
        /// <param name="self">the container of the extension</param>
        /// <returns>the string which contains the values</returns>
        public static string UnParse(this Vector3 self)
        {
            return string.Format("{0}|{1}|{2}", self.X, self.Y, self.Z);
        }
        #endregion

        #region Vector2
        /// <summary>
        /// Tries to parse a Vector2
        /// </summary>
        /// <param name="input">the string to parse</param>
        /// <param name="result">the value which the input-string contained</param>
        /// <returns>true, if the parsing process was successful, otherwise false</returns>
        public static bool TryParse(string input, out Vector2 result)
        {
            string[] parts = input.Split(new char[] { '|', '/', ',', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);

            result = new Vector2();
            float x, y;
            if (   parts.Length == 2
                && float.TryParse(parts[0], out x) 
                && float.TryParse(parts[1], out y))
            {
                result.X = x;
                result.Y = y;
                return true;
            }
            return false;
        }
        /// <summary>
        /// writes all relevant values to a string which can be parsed by ParseHelper.TryParse()
        /// </summary>
        /// <param name="self">the container of the extension</param>
        /// <returns>the string which contains the values</returns>
        public static string UnParse(this Vector2 self)
        {
            return string.Format("{0}|{1}", self.X, self.Y);
        }
        #endregion

        #region Rectangle
        /// <summary>
        /// Parses a Rectangle
        /// </summary>
        /// <param name="input">the string to parse</param>
        /// <returns>the value which the input-string contained</returns>
        public static Rectangle ParseRectangle(string input)
        {
            Rectangle rect;
            if (!TryParse(input, out rect))
                throw new Exception("couldn't parse rect");
            return rect;
        }
        /// <summary>
        /// Tries to parse a Rectangle
        /// </summary>
        /// <param name="input">the string to parse</param>
        /// <param name="result">the value which the input-string contained</param>
        /// <returns>true, if the parsing process was successful, otherwise false</returns>
        public static bool TryParse(string input, out Rectangle result)
        {
            string[] parts = input.Split(new char[] { '|', '/', ',', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);

            result = new Rectangle();
            int x, y, width, height;
            if (   parts.Length == 4
                && int.TryParse(parts[0], out x) 
                && int.TryParse(parts[1], out y) 
                && int.TryParse(parts[2], out width)
                && int.TryParse(parts[3], out height))
            {
                result.X = x;
                result.Y = y;
                result.Width = width;
                result.Height = height;
                return true;
            }
            return false;
        }
        /// <summary>
        /// writes all relevant values to a string which can be parsed by ParseHelper.TryParse()
        /// </summary>
        /// <param name="self">the container of the extension</param>
        /// <returns>the string which contains the values</returns>
        public static string UnParse(this Rectangle self)
        {
            return string.Format("{0}|{1}/{2}|{3}", self.X, self.Y, self.Width, self.Height);
        }
        #endregion

        #region Color
        /// <summary>
        /// Tries to parse a Color
        /// </summary>
        /// <param name="input">the string to parse</param>
        /// <param name="result">the value which the input-string contained</param>
        /// <returns>true, if the parsing process was successful, otherwise false</returns>
        public static bool TryParse(string input, out Color result)
        {
            string[] parts = input.Split(new char[] { '|', '/', ',', ';', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);

            result = new Color();
            byte r, g, b, a;
            if ((parts.Length == 3 || parts.Length == 4)
                && byte.TryParse(parts[0], out r) 
                && byte.TryParse(parts[1], out g)
                && byte.TryParse(parts[2], out b))
            {
                if (parts.Length == 3 || !byte.TryParse(parts[3], out a))
                    a = 255;

                result.R = r;
                result.G = g;
                result.B = b;
                result.A = a;
                
                return true;
            }
            return false;
        }
        /// <summary>
        /// writes all relevant values to a string which can be parsed by ParseHelper.TryParse()
        /// </summary>
        /// <param name="self">the container of the extension</param>
        /// <returns>the string which contains the values</returns>
        public static string UnParse(this Color self)
        {
            return string.Format("{0}|{1}|{2}/{3}", self.R, self.G, self.B, self.A);
        }
        #endregion

    }
}
